/*
 * Generador de codigo intermedio
 * para el proyecto de compiladores
 * Codigo intermedio usa CUARTETOS
 */

// Necesitamos abrir ficheros, lo que implica usar el stdio
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "sint.h"
#include "ts2006.h"

// Declaracion de funciones 
int escribir_string (char * linea);
int escribir_entero (int linea);
extern FILE *fintermedio;
extern FILE *ffinal;
extern int tabla_simbolos[MAX];
extern int cima;
extern int sigo_generando_codigo_final;
extern int encuentra_en_ts(char *id);
extern unsigned short push_hechos;
extern void emite_busca_tabla(int saltos);
extern int limpiar_parentesis (char* nombre);
extern int numero_etiqueta;

int emite (clase tipo_op, char * primero, char * segundo, char* tercero) {
  int desp_primero      = 0;
  int desp_segundo      = 0;
  int desp_tercero      = 0;
  //  int ts            = tabla_simbolos[cima];  // No se si se usara
  int n_primero         = limpiar_parentesis (primero);  // limpia
  int n_segundo         = limpiar_parentesis (segundo);  // limpia
  int n_tercero         = limpiar_parentesis (tercero);  // limpia
  int cima_primero      = encuentra_en_ts(primero);
  int cima_segundo      = encuentra_en_ts(segundo);
  int cima_tercero      = encuentra_en_ts(tercero);
  int saltos_PA_primero = cima - cima_primero;
  int saltos_PA_segundo = cima - cima_segundo;
  int saltos_PA_tercero = cima - cima_tercero;
  int min_primero       = 0;
  int min_segundo       = 0;
  int min_tercero       = 0;
  int max_primero       = 0;
  int max_segundo       = 0;
  int max_tercero       = 0;

  if (sigo_generando_codigo_final) {
    //  Hay una funcion auxiliar para consultar todas las ts <- usar
    if (cima_primero != -1) {
      desp_primero =
        (consultar_valor_atributo_entero(tabla_simbolos[cima_primero],
                                         primero, "desplazamiento"))/4;
    }
    if (cima_segundo != -1) {
      desp_segundo =
        (consultar_valor_atributo_entero(tabla_simbolos[cima_segundo],
                                         segundo, "desplazamiento"))/4;
    }
    if (cima_tercero != -1) {
      desp_tercero =
        (consultar_valor_atributo_entero(tabla_simbolos[cima_tercero],
                                         tercero, "desplazamiento"))/4;
    }
    
    //  Calculo los minimos, si los hubiera
    if ((desp_primero) && 
        (existe_atributo(tabla_simbolos[cima_primero], primero, "min") == 0)) {
      min_primero = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_primero],
                                         primero,
                                         "min");
    }
    if ((desp_segundo) &&
        (existe_atributo(tabla_simbolos[cima_segundo], segundo, "min") == 0)) {
      min_segundo = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_segundo],
                                         segundo,
                                         "min");
    }
    if ((desp_tercero) &&
        (existe_atributo(tabla_simbolos[cima_tercero], tercero, "min") == 0)) {
      min_tercero = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_tercero],
                                         tercero,
                                         "min");
    }
    
    //  Calculo los maximos, si los hubiera
    if ((desp_primero) && 
        (existe_atributo(tabla_simbolos[cima_primero], primero, "max") == 0)) {
      max_primero = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_primero],
                                         primero,
                                         "max");
    }
    if ((desp_segundo) &&
        (existe_atributo(tabla_simbolos[cima_segundo], segundo, "max") == 0)) {
      max_segundo = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_segundo],
                                         segundo,
                                         "max");
    }
    if ((desp_tercero) &&
        (existe_atributo(tabla_simbolos[cima_tercero], tercero, "max") == 0)) {
      max_tercero = 
        consultar_valor_atributo_entero (tabla_simbolos[cima_tercero],
                                         tercero,
                                         "max");
    }
    
    if ((desp_primero) && (n_primero >= min_primero)) {
      desp_primero += (n_primero - min_primero);
    } else if (desp_primero) {
        printf ("fallo en %d %s %s %s\n",
                tipo_op, primero, segundo, tercero);
        printf ("se intento acceder al elto %d del vector %s y empieza en %d\n",
                n_primero, primero, min_primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
    }
    if ((desp_segundo) && (n_segundo >= min_segundo)) {
      desp_segundo += (n_segundo - min_segundo);
    } else if (desp_segundo) {
        printf ("fallo en %d %s %s %s\n",
                tipo_op, primero, segundo, tercero);
        printf ("se intento acceder al elto %d del vector %s y empieza en %d\n",
                n_segundo, segundo, min_segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
    }
    if ((desp_tercero) && (n_tercero >= min_tercero)) {
      desp_tercero += (n_tercero - min_tercero);
    } else if (desp_tercero) {
        printf ("fallo en %d %s %s %s\n",
                tipo_op, primero, segundo, tercero);
        printf ("se intento acceder al elto %d del vector %s y empieza en %d\n",
                n_tercero, tercero, min_tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
    }

    if ((desp_primero) && (n_primero > max_primero)) {
      printf ("fallo en %d %s %s %s\n",
              tipo_op, primero, segundo, tercero);
      printf ("se intento acceder al elto %d del vector %s y termina en %d\n",
              n_primero, primero, max_primero);
      printf ("ya no se continuara generando codigo final\n");
      sigo_generando_codigo_final = 0;
    }
    if ((desp_segundo) && (n_segundo > max_segundo)) {
      printf ("fallo en %d %s %s %s\n",
              tipo_op, primero, segundo, tercero);
      printf ("se intento acceder al elto %d del vector %s y termina en %d\n",
              n_segundo, segundo, max_segundo);
      printf ("ya no se continuara generando codigo final\n");
      sigo_generando_codigo_final = 0;
    }
    if ((desp_tercero) && (n_tercero > max_tercero)) {
      printf ("fallo en %d %s %s %s\n",
              tipo_op, primero, segundo, tercero);
      printf ("se intento acceder al elto %d del vector %s y termina en %d\n",
              n_tercero, tercero, max_tercero);
      printf ("ya no se continuara generando codigo final\n");
      sigo_generando_codigo_final = 0;
    }
  }

  switch (tipo_op) {
  case n_suma:  // primero := segundo + tercero;
    fprintf(fintermedio, "(suma,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      //  No tocar los espacios (que asi lo pinta bien)
      fprintf(ffinal, "                   ;  <<%s := %s + %s>>\n",
              primero, segundo, tercero);
      if (desp_primero) {
        emite_busca_tabla(saltos_PA_primero);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE [.A],   .R9   ;  .R9 = primero.direccion\n");
      } else {
        printf ("fallo en la suma %s := %s + %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (desp_segundo) { 
        emite_busca_tabla(saltos_PA_segundo);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(segundo.direccion)\n",
                desp_segundo);
        fprintf(ffinal, "MOVE [.A],   .R8  ;  .R8 = segundo.direccion\n");
        fprintf(ffinal, "MOVE [.R8],  .R7  ;  .R7 = segundo.valor\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,   .R7   ;  .R7 = segundo.valor\n",
                atoi(segundo));
      }

      if (desp_tercero) { 
        emite_busca_tabla(saltos_PA_tercero);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(tercero.direccion)\n",
                desp_tercero);
        fprintf(ffinal, "MOVE [.A],   .R6   ;  .R6 = tercero.direccion\n");
        fprintf(ffinal, "MOVE [.R6],  .R5   ;  .R5 = tercero.valor\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,   .R5   ;  .R5 = tercero.valor\n",
                atoi(tercero));
      }

      fprintf(ffinal, "ADD   .R7,   .R5   ;  .A = segundo.valor + tercero.valor\n");
      fprintf(ffinal, "MOVE  .A,   [.R9]  ;  .A = segundo.valor + tercero.valor\n");
    }
    break;

  case n_rel:  //  primero := segundo > tercero;
    fprintf(fintermedio, "(es_mayor,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  <<%s := %s > %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        emite_busca_tabla(saltos_PA_primero);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE [.A],   .R9   ;  .R9 = primero.direccion\n");
      } else {
        printf ("fallo en la asignacion relacional %s := %s > %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (desp_segundo) { 
        emite_busca_tabla(saltos_PA_segundo);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(primero.direccion)\n",
                desp_segundo);
        fprintf(ffinal, "MOVE [.A],   .R8   ;  .R8 = segundo.direccion\n");
        fprintf(ffinal, "MOVE [.R8],  .R7   ;  .R7 = segundo.valor\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,  .R7   ;  .R7 = segundo.valor\n",
                atoi(segundo));
      }

      if (desp_tercero) { 
        emite_busca_tabla(saltos_PA_tercero);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(primero.direccion)\n",
                desp_tercero);
        fprintf(ffinal, "MOVE [.A],   .R6  ;  .R6 = tercero.direccion\n");
        fprintf(ffinal, "MOVE [.R6],  .R5  ;  .R5 = tercero.valor\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,   .R5   ;  .R5 = tercero.valor\n",
                atoi(tercero));
      }

      fprintf(ffinal, "CMP   .R7,   .R5   ;  .A = segundo.valor CMP tercero.valor\n");
      fprintf(ffinal, "BN   $5            ;  .PC = .PC+ 3\n");
      fprintf(ffinal, "MOVE #1,    [.R9]  ;  .R9 = 0\n");
      fprintf(ffinal, "BR   $3            ;  .PC = .PC+ 3\n");
      fprintf(ffinal, "MOVE #0,    [.R9]  ;  .R9 = 1\n");
    }
    break;

  case n_and:  //  primero := segundo && tercero;
    fprintf(fintermedio, "(and,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  <<%s := %s && %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        fprintf(ffinal, "ADD  #%.3d,   .SP   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE [.A],   .R9   ;  .R9 = primero.direccion\n");
      } else {
        printf ("fallo en la asignacion relacional %s := %s > %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (desp_segundo) { 
        fprintf(ffinal, "ADD  #%.3d,   .SP  ;  .A = MEM(segundo.direccion)\n",
                desp_segundo);
        fprintf(ffinal, "MOVE [.A],    .R8  ;  .R8 = segundo.direccion\n");
        fprintf(ffinal, "MOVE [.R8],   .R7  ;  .R7 = segundo.valor\n");
      } else if (strncmp(segundo,"true", 4) == 0) {
        fprintf(ffinal, "MOVE #1,     .R7   ;  .R7 = true\n");
      } else if  (strncmp(segundo,"false", 5) == 0) {
        fprintf(ffinal, "MOVE #0,     .R7   ;  .R7 = false\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,   .R7   ;  .R7 = segundo.valor\n",
                atoi(segundo));
      }

      if (desp_tercero) { 
        fprintf(ffinal, "ADD  #%.3d,  .SP  ;  .A = MEM(tercero.direccion)\n",
                desp_segundo);
        fprintf(ffinal, "MOVE [.A],  .R6  ;  .R6 = tercero.direccion\n");
        fprintf(ffinal, "MOVE [.R6], .R5  ;  .R5 = tercero.valor\n");
      } else if (strncmp(tercero,"true", 4) == 0) {
        fprintf(ffinal, "MOVE #1,     .R5   ;  .R5 = true\n");
      } else if  (strncmp(tercero,"false", 5) == 0) {
        fprintf(ffinal, "MOVE #0,     .R5   ;  .R5 = false\n");
      }else {
        fprintf(ffinal, "MOVE #%.3d,   .R5   ;  .R5 = tercero.valor\n",
                atoi(tercero));
      }

      fprintf(ffinal, "AND   .R7,   .R5   ;  .A = segundo.valor && tercero.valor\n");
      fprintf(ffinal, "MOVE  .A,    .R9   ;  primero.dir = .A\n");
    }
    break;

  case n_endif:
    fprintf(fintermedio, "(endif,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  << endif %s %s %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s es una variable encontrada en algun tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      fprintf(ffinal, "BR  /%s            ;  goto $%s\n",
              primero, primero);
    }
    break;

  case n_asignacion:  //  primero := segundo;
    fprintf(fintermedio, "(asignacion,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      //  No tocar los espacios (que asi lo pinta bien)
      fprintf(ffinal, "                   ;  <<%s := %s %s>>\n",
              primero, segundo, tercero);
      if (desp_primero) { 
        emite_busca_tabla(saltos_PA_primero);
        fprintf(ffinal, "ADD  #%.3d,   .R0   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE  [.A],    .R9   ;  .R9 = primero.direccion\n");
      } else {
        printf ("fallo en la suma %s := %s + %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (desp_segundo) { 
        fprintf(ffinal, "ADD  #%.3d,   .SP   ;  .A = MEM(segundo.direccion)\n",
                desp_segundo);
        fprintf(ffinal, "MOVE [.A],   .R8   ;  .R8 = segundo.direccion\n");
        fprintf(ffinal, "MOVE [.R8],  .R7   ;  .R7 = segundo.valor\n");
      } else if (strncmp(segundo,"true", 4) == 0) {
        fprintf(ffinal, "MOVE #1,     .R7   ;  .R7 = true\n");
      } else if  (strncmp(segundo,"false", 5) == 0) {
        fprintf(ffinal, "MOVE #0,     .R7   ;  .R7 = true\n");
      } else {
        fprintf(ffinal, "MOVE #%.3d,   .R7   ;  .R7 = segundo.valor\n",
                atoi(segundo));
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en una asignacion %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      fprintf(ffinal, "MOVE  .R7,    [.R9]  ;  .R9 = segundo.valor + tercero.valor\n");
    }
    break;

  case n_push:  //  PUSH primero
    fprintf(fintermedio, "(push,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  << push %s %s %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        desp_primero += push_hechos;
        fprintf(ffinal, "ADD  #%.3d,   .SP   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE [.A],   .R9   ;  .R9 = primero.direccion\n");
      } else {
        printf ("fallo en el push %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      fprintf(ffinal, "PUSH  .R9          ;  push $%s.direccion\n",
              primero);
      push_hechos ++;
    }
    break;	

  case n_label:
    fprintf(fintermedio, "(etiqueta,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  <<%s : %s %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        printf ("fallo en la etiqueta %s : %s %s\n",
                primero, segundo, tercero);
        printf ("%s es una variable encontrada en alguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      fprintf(ffinal, "%s :               ;  %s etiqueta\n",
              primero, primero);
    }
    break;

  case n_halt:
    fprintf(fintermedio, "(halt,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  <<%s : %s %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el halt %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el halt %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el halt %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      fprintf(ffinal, "MOVE  #0,    .A    ;  .A = 0\n");
      fprintf(ffinal, "TOTALFIN :         ;  Fin del todo\n");
      fprintf(ffinal, "HALT               ;  HALT\n");
      fprintf(ffinal, "HALT               ;  HALT\n");
      fprintf(ffinal, "CIMA     : DATA 0  ;  cima_actual\n");
      fprintf(ffinal, "NCIMA    : DATA 0  ;  n_cima_actual\n");
    }
    break;

  case n_false:  //  emite(n_false,$2->lexema,etiqueta[numero_etiqueta] ,"-");
    fprintf(fintermedio, "(if_false,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  << if_false %s goto %s %s>>\n",
              primero, segundo, tercero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        fprintf(ffinal, "ADD  #%.3d,   .SP   ;  .A = MEM(primero.direccion)\n",
                desp_primero);
        fprintf(ffinal, "MOVE [.A],   .R9   ;  .R9 = primero.direccion\n");
        fprintf(ffinal, "MOVE [.R9],  .R8   ;  .R8 = primero.valor\n");
      } else {
        printf ("fallo en el n_false %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (desp_segundo) {
        printf ("fallo en el n_false %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s es una variable encontrada en alguna tabla de simbolos\n",
                segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el if_false %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      fprintf(ffinal, "CMP   .R8,  #0     ;  .A = .R8 CMP #0\n");
      fprintf(ffinal, "BZ   /%s           ;  goto /%s\n", segundo, segundo);
    }
    break;

  case n_call:  //  ncall funcion n
    fprintf(fintermedio, "(call,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ; <<call %s %s %s>>\n",
              primero, segundo, tercero);
      //  Habria que buscar que sea el primero el nombre de un procedure
      if (desp_primero) { 
        printf ("fallo en el push %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es una variable encontrada en ninguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) ==0) { 
        printf ("fallo en el call %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el call %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      fprintf(ffinal, "PUSH #%.3d          ;  push $%.3d para luego un call\n",
              atoi(segundo), atoi(segundo));
      fprintf(ffinal, "#include %s.tabla\n",
              primero);
      fprintf(ffinal, "fin%s%d :       ;  etiqueta $%s%d para retornar\n",
              primero, numero_etiqueta,primero, numero_etiqueta);
      fprintf(ffinal, "MOVE  /CIMA,    .R9  ;  .R9 = CIMA_anterior\n");
      fprintf(ffinal, "DEC    .R9           ;  \n");
      fprintf(ffinal, "MOVE   .R9,    /CIMA ;  CIMA = CIMA_nueva\n");
      fprintf(ffinal, "MOVE  #1,      /NCIMA ; No es real, pero nos sirve\n");
      numero_etiqueta++;
    }
    break;
    
  case n_ret:
    fprintf(fintermedio, "(ret,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ; <<ret %s %s %s>>\n",
              primero, segundo, tercero);
      //  Habria que buscar que sea el primero el nombre de un procedure
      if (strncmp(segundo, "-", 1) !=0) {  
        printf ("fallo en el ret %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el ret %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el ret %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      fprintf(ffinal, "                   ;  parece que es el final\n");
      fprintf(ffinal,
              "ADD   #1,    .SP   ;  .A  = dir_retorno.direccion\n");
      fprintf(ffinal, "MOVE [.A],    .R9  ;  .R9 = dir_retorno\n");
      fprintf(ffinal, "ADD   #2,    .SP   ;  .A  = npush.direccion\n");
      fprintf(ffinal, "MOVE  .A,    .R8   ;  .R8 = npush.direccion\n");
      fprintf(ffinal, "MOVE [.R8],  .R7   ;  .R7 = npush\n");
      fprintf(ffinal, "MOVE  .R7,   .R6   ;  cuantos_a_0 = npush\n");
      fprintf(ffinal, "INC   .SP          ;  .SP ++\n");
      fprintf(ffinal, "CMP   .R6,   #0    ;  .A   = CMP .R3 #0\n");
      fprintf(ffinal,
              "BZ    $9          ;  if copiar_a_0 ==0 goto retornar\n");
      fprintf(ffinal, "MOVE  #0,   [.SP]  ;  MEM(.SP) = 0\n");
      fprintf(ffinal, "DEC   .R6          ;  cuantos_a_0 --\n");
      fprintf(ffinal, "INC   .SP          ;  elto_a_copiar.dir ++\n");
      fprintf(ffinal, "BR    $-14         ;  goto if copiar_eltos==0\n");
      fprintf(ffinal, "DEC   .SP          ;  reajustamos el .SP\n");
      fprintf(ffinal, "                   ;  quitamos los parametros\n");
      fprintf(ffinal, "MOVE  .R9,   .PC   ;  retornamos\n");
    }

    break;

  case n_goto:
    fprintf(fintermedio, "(goto,%s,%s,%s)\n", primero, segundo, tercero);
    if (sigo_generando_codigo_final) {
      fprintf(ffinal, "                   ;  <<GOTO %s>>\n",
              primero);
      //  No tocar los espacios (que asi lo pinta bien)
      if (desp_primero) { 
        printf ("fallo en la etiqueta %s : %s %s\n",
                primero, segundo, tercero);
        printf ("%s es una variable encontrada en alguna tabla de simbolos\n",
                primero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      if (strncmp(segundo, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", segundo);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }

      if (strncmp(tercero, "-", 1) !=0) { 
        printf ("fallo en el endif %s %s %s\n",
                primero, segundo, tercero);
        printf ("%s no es un -\n", tercero);
        printf ("ya no se continuara generando codigo final\n");
        sigo_generando_codigo_final = 0;
      }
      
      fprintf(ffinal, "BR  /%s        ;  goto /%s\n",
              primero, primero);
    }
    break;
  }
  return 0;
}

